package com.xy.stock.config;

import org.redisson.api.RBloomFilter;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.*;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class RedisSingleUtil {

    @Autowired
    @Qualifier("redisSingleTemplate")
    private RedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    //如果缓存需要预热 ，就先拿连接 比较快
//    @PostConstruct
//    public void init(){
//        RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
//        RedisConnection conn = RedisConnectionUtils.getConnection(factory);
//    }


    //bloom过滤器 其实就是一个key 经过不同算法的hash散列 等查询的时候 还用同样的办法 如果两次结果相同 就存在，否则就不存在
    @PostConstruct
    public void init(){
        RBloomFilter rBloomFilter = redissonClient.getBloomFilter("newStateBlomList");
        rBloomFilter.tryInit(10000l,0.03);
        Set<String> stringSet = keys("KC_2");
        if(stringSet!=null) {
            stringSet.forEach((key)->{
                rBloomFilter.add(key);
            });
        }
    }

    //查询的时候需要查询完整key
    public Boolean blomIsExist(String key){
        RBloomFilter rBloomFilter = redissonClient.getBloomFilter("newStateBlomList");
        return rBloomFilter.contains(key);
    }


    public void lock(String key){
        RLock rLock = redissonClient.getLock(key);
        rLock.lock();
    }


    public void unlock(String key){
        RLock rLock = redissonClient.getLock(key);
        rLock.unlock();
    }


    public Set<String> keys(String keyPrefix) {
        String realKey = "*" + keyPrefix + "*";
        try {
            return (Set<String>) redisTemplate.execute((RedisCallback<Set<String>>) connection -> {
                Set<String> binaryKeys = new HashSet<>();
                Cursor<byte[]> cursor = connection.scan(new ScanOptions.ScanOptionsBuilder().match(realKey).count(Integer.MAX_VALUE).build());
                while (cursor.hasNext()) {
                    binaryKeys.add(new String(cursor.next()));
                }
                return binaryKeys;
            });
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }


    public void set(String key,Object value){
        redisTemplate.opsForValue().set(key,value);
    }

    public void set(String key, Object value, long timeout, TimeUnit unit){
        redisTemplate.opsForValue().set(key,value,timeout,unit);
    }

    public <V> void putListAllRight(String key, Collection<V> values){
        if(CollectionUtils.isEmpty(values)){
        }else{
            redisTemplate.opsForList().rightPushAll(key,values);
        }
    }

    public <T> T getListAll(String key,Class<?> T){
        return (T)redisTemplate.opsForList().range(key,0,-1);
    }

    public <T> T get(String key,Class<?> T){
        return (T)redisTemplate
                .opsForValue().get(key);
    }

    public String get(String key){
        return (String) redisTemplate
                .opsForValue().get(key);
    }

    public Long decr(String key){
        return redisTemplate
                .opsForValue().decrement(key);
    }

    public Long decr(String key,long delta){
        return redisTemplate
                .opsForValue().decrement(key,delta);
    }

    public Long incr(String key){
        return redisTemplate
                .opsForValue().increment(key);
    }

    public Long incr(String key,long delta){
        return redisTemplate
                .opsForValue().increment(key,delta);
    }

    public boolean expire(String key,long timeout,TimeUnit unit){
        return redisTemplate.expire(key,timeout, unit);
    }

    public boolean delete(String key){
        return redisTemplate.delete(key);
    }

    public boolean hasKey(String key){
        return redisTemplate.hasKey(key);
    }

}
